package me.stone.stanimeclient.core.ui.helpers

import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import me.stone.stanimeclient.core.common.utils.WhileViewSubscribed
import me.stone.stanimeclient.core.model.BatteryState
import kotlin.math.ceil

class BatteryStateHelper(private val activity: AppCompatActivity) {

    private val _charging by lazy { MutableStateFlow(false) }

    val charging: StateFlow<Boolean>
        get() = _charging
            .distinctUntilChangedBy { it }
            .stateIn(activity.lifecycleScope, WhileViewSubscribed, false)

    private val _battery by lazy { MutableStateFlow(BatteryState.Full) }

    val battery: StateFlow<BatteryState>
        get() = _battery
            .distinctUntilChangedBy { it }
            .stateIn(activity.lifecycleScope, WhileViewSubscribed, BatteryState.Full)

    fun request() {
        val batteryStatus = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let {
            activity.registerReceiver(null, it)
        } ?: return

        if (batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1).let {
            it == BatteryManager.BATTERY_STATUS_CHARGING || it == BatteryManager.BATTERY_STATUS_FULL
        }) {
            activity.lifecycleScope.launch { _charging.emit(true) }
            activity.lifecycleScope.launch { _battery.emit(BatteryState.Charging) }
            return
        }

        val level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
        val scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
        val percentage = ceil(level * 100f / scale).toInt()
        val battery = when (percentage) {
            in 70 .. 100 -> BatteryState.Full
            in 40 ..< 70 -> BatteryState.Medium
            in 10 ..< 40 -> BatteryState.Low
            else -> BatteryState.Warning
        }
        activity.lifecycleScope.launch { _battery.emit(battery) }
    }

    private var updateLoopRequestEnable = false

    init {
        activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
            private var loopJob: Job? = null

            override fun onResume(owner: LifecycleOwner) {
                loopJob?.cancel()
                loopJob = activity.lifecycleScope.launch {
                    while (true) {
                        if (updateLoopRequestEnable) {
                            request()
                        }
                        delay(1000)
                    }
                }
            }

            override fun onPause(owner: LifecycleOwner) {
                loopJob?.cancel()
                loopJob = null
            }
        })
    }

    fun updateEnableLoopRequest(enable: Boolean) {
        updateLoopRequestEnable = enable
    }

}